from gm.api import order_volume, get_unfinished_orders, order_value
from gm.enum import OrderType_Market, OrderSide_Sell, PositionEffect_Close, PositionSide_Long, PositionEffect_Open, \
    OrderSide_Buy, OrderDuration_FOK


def today_position_number(context):
    today_positions_num = 0
    account_positions = context.account().positions()
    if len(account_positions) > 0:
        for position in account_positions:
            if position.volume_today > 0:
                today_positions_num += 1
    return today_positions_num


def is_position_trading(context, symbol):
    """
    某个品种是否正在持仓或者正在处理或者委托
    """
    is_true = had_position(context, symbol)
    if not is_true:
        is_true = had_ordering(symbol)
    return is_true


def had_position(context, symbol):
    """
    某个品种是否有持仓
    :param context:
    :param symbol:
    :return:
    """
    account_position = context.account().position(symbol=symbol, side=PositionSide_Long)
    if account_position is not None:
        return True
    return False


def can_full_close(context, symbol):
    """
    是否可全部平仓
    """
    account_position = context.account().position(symbol=symbol, side=PositionSide_Long)
    if account_position is None:
        return False
    if account_position.volume_today == 0:
        return True
    return False


def had_ordering(symbol):
    """
    是否为委托中订单
    :param symbol:
    :return:
    """
    unfinished_orders = get_unfinished_orders()
    if len(unfinished_orders) == 0:
        return False
    for order in unfinished_orders:
        if symbol == order['symbol']:
            return True
    return False


def get_account_fnpl_rate(context):
    """
    获取帐户盈利比例
    :param context:
    :return:
    """
    fpnl_rate = context.account().cash.fpnl / (context.account().cash.nav - context.account().cash.fpnl) * 100
    return fpnl_rate


def get_order_fpnl_rate(account_position):
    """
    获取订单盈利比例
    :param account_position:
    :return:
    """
    fpnl_rate = (account_position.market_value - account_position.amount) / account_position.amount * 100
    return fpnl_rate


def position_total_rate(context):
    return context.account().cash.order_frozen / context.account().cash.nav * 100


def can_close_today(account_position):
    """
        今日可平仓股数
    """
    return account_position.available - account_position.available_today


def do_close_order_at_market_by_volume(symbol, volume):
    """
    市价平仓
    :param symbol:
    :param volume:
    :return:
    """
    return order_volume(symbol=symbol,
                        volume=volume,
                        side=OrderSide_Sell, order_type=OrderType_Market,
                        position_effect=PositionEffect_Close, price=11, order_duration=OrderDuration_FOK)


def do_order_at_market_by_volume(symbol, volume):
    """
    市价平仓
    :param symbol:
    :param volume:
    :return:
    """
    orders = order_volume(symbol=symbol, volume=volume, side=OrderSide_Buy,
                          order_type=OrderType_Market,
                          position_effect=PositionEffect_Open, order_duration=OrderDuration_FOK)
    return orders


def do_order_at_market_by_value(symbol, value):
    """
    市价平仓
    :param symbol:
    :param value:
    :return:
    """
    orders = order_value(symbol=symbol, value=value, side=OrderSide_Buy,
                         order_type=OrderType_Market,
                         position_effect=PositionEffect_Open, order_duration=OrderDuration_FOK)
    return orders


def is_morning_collection_bidding(context):
    """
    是否为早盘集合竞价时间
    :return:
    """
    now_date = context.now.strftime("%H:%M:%S")
    if now_date < '9:30:00':
        return True
    return False


def is_afternoon_collection_bidding(context):
    """
    是否为尾盘集合竞价时间
    :return:
    """
    now_date = context.now.strftime("%H:%M:%S")
    if now_date >= '14:53:00':
        return True
    return False


def auto_tp_sl_all_can_close_orders_market(context, tp_rate, close_rate):
    """
        达到止损止盈比例自动按市价止损止盈
    """
    orders = list()
    account_position = context.account().positions()
    if len(account_position) == 0:
        return orders
    for account_position in account_position:
        fpnl_rate = get_order_fpnl_rate(account_position)
        if fpnl_rate >= tp_rate or fpnl_rate <= close_rate:
            today_can_close = can_close_today(account_position)
            if today_can_close > 0:
                orders = do_close_order_at_market_by_volume(account_position.symbol, today_can_close)
    return orders


def can_close_symbol(context, symbol):
    if had_position(context, symbol) and (can_full_close(context, symbol) == True) and (had_ordering(symbol) == False):
        return True
    return False


def can_open_symbol(context, symbol):
    if had_position(context, symbol) == False and had_ordering(symbol) == False:
        return True
    return False
